package com.sgcc.nfc.lock.presentation.users

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sgcc.nfc.lock.core.network.NetworkResult
import com.sgcc.nfc.lock.domain.model.Region
import com.sgcc.nfc.lock.domain.model.RegionLevel
import com.sgcc.nfc.lock.domain.model.RoleType
import com.sgcc.nfc.lock.domain.model.UserProfile
import com.sgcc.nfc.lock.domain.repository.UserRepository
import com.sgcc.nfc.lock.domain.usecase.CreateUserUseCase
import com.sgcc.nfc.lock.domain.usecase.GetProfileUseCase
import com.sgcc.nfc.lock.domain.usecase.GetRegionTreeUseCase
import com.sgcc.nfc.lock.domain.usecase.UpdateUserUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch

@HiltViewModel
class UserFormViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val createUserUseCase: CreateUserUseCase,
    private val updateUserUseCase: UpdateUserUseCase,
    private val getRegionTreeUseCase: GetRegionTreeUseCase,
    private val getProfileUseCase: GetProfileUseCase
) : ViewModel() {

    val userId: Long? = savedStateHandle.get<Long>("userId")
    private val usernameArg: String? = savedStateHandle.get<String>("username")
    private val realNameArg: String? = savedStateHandle.get<String>("realName")
    private val phoneArg: String? = savedStateHandle.get<String>("phone")
    private val roleTypeArg: Int? = savedStateHandle.get<Int>("roleType")
    private val regionIdArg: Long? = savedStateHandle.get<Long>("regionId")

    val username = MutableLiveData(usernameArg)
    val realName = MutableLiveData(realNameArg)
    val phone = MutableLiveData(phoneArg)
    val password = MutableLiveData<String?>(null)

    val regionId = MutableLiveData<Long?>(regionIdArg)

    private val _roleType = MutableLiveData<RoleType?>(RoleType.fromValue(roleTypeArg))
    val roleType: LiveData<RoleType?> = _roleType

    private val _roleOptions = MutableLiveData<List<RoleType>>(emptyList())
    val roleOptions: LiveData<List<RoleType>> = _roleOptions

    private val _regionItems = MutableLiveData<List<SelectableRegionItem>>(emptyList())
    val regionItems: LiveData<List<SelectableRegionItem>> = _regionItems

    private val _isLoadingRegions = MutableLiveData(false)
    val isLoadingRegions: LiveData<Boolean> = _isLoadingRegions

    private val _submitSuccess = MutableLiveData<Boolean>()
    val submitSuccess: LiveData<Boolean> = _submitSuccess

    private val _error = MutableLiveData<ErrorMessage?>()
    val error: LiveData<ErrorMessage?> = _error

    private var currentUser: UserProfile? = null
    private val regionIndex = mutableMapOf<Long, Region>()
    private var selectableRegionMap: Map<Long, SelectableRegionItem> = emptyMap()
    private var regionsLoaded = false

    init {
        loadRegions()
    }

    fun loadRegions(force: Boolean = false) {
        if (regionsLoaded && !force) return
        
        viewModelScope.launch {
            _isLoadingRegions.value = true
            try {
                ensureCurrentUser()
                
                when (val result = getRegionTreeUseCase()) {
                    is NetworkResult.Success -> {
                        val tree = result.data
                        rebuildRegionIndex(tree)
                        
                        val filteredTree = applyAccessControl(tree)
                        val items = mutableListOf<SelectableRegionItem>()
                        appendRegions(filteredTree, 0, null, items)
                        
                        selectableRegionMap = items.associateBy { it.id }
                        _regionItems.value = items
                        
                        val initialRegionId = determineInitialRegionId(items)
                        regionId.value = initialRegionId
                        
                        val selectedItem = initialRegionId?.let { selectableRegionMap[it] }
                        applyRoleOptionsForSelection(selectedItem)
                        
                        regionsLoaded = true
                    }
                    is NetworkResult.Error -> {
                        _error.value = ErrorMessage.Custom(result.message ?: "加载区域失败")
                    }
                    is NetworkResult.Loading -> {
                        // 保持加载状态
                    }
                }
            } catch (e: Exception) {
                _error.value = ErrorMessage.Custom(e.message ?: "加载区域失败")
            } finally {
                _isLoadingRegions.value = false
            }
        }
    }

    fun onRegionSelected(item: SelectableRegionItem) {
        regionId.value = item.id
        applyRoleOptionsForSelection(item)
        _error.value = null
    }

    fun onRoleSelected(role: RoleType) {
        _roleType.value = role
        _error.value = null
    }

    fun submit() {
        val usernameValue = username.value?.trim().orEmpty()
        val realNameValue = realName.value?.trim().orEmpty()
        val phoneValue = phone.value?.trim()
        val selectedRegionId = regionId.value

        if (usernameValue.isBlank() || realNameValue.isBlank()) {
            _error.value = ErrorMessage.MissingBasicInfo
            return
        }
        if (selectedRegionId == null) {
            _error.value = ErrorMessage.MissingRegion
            return
        }

        val selectedItem = selectedRegionId?.let { selectableRegionMap[it] }
        val availableRoles = availableRolesFor(selectedItem)
        if (availableRoles.isEmpty()) {
            _error.value = ErrorMessage.MissingRole
            return
        }

        val resolvedRole = _roleType.value?.takeIf { availableRoles.contains(it) }
            ?: availableRoles.first()

        viewModelScope.launch {
            try {
                val result = if (userId == null) {
                    // 创建新用户
                    createUserUseCase(
                        UserRepository.CreateUserParams(
                            username = usernameValue,
                            password = password.value?.trim().orEmpty(),
                            realName = realNameValue,
                            phone = phoneValue,
                            roleType = resolvedRole.value,
                            regionId = selectedRegionId
                        )
                    )
                } else {
                    // 更新现有用户
                    updateUserUseCase(
                        UserRepository.UpdateUserParams(
                            userId = userId,
                            realName = realNameValue,
                            phone = phoneValue,
                            roleType = resolvedRole.value,
                            regionId = selectedRegionId
                        )
                    )
                }
                
                when (result) {
                    is NetworkResult.Success -> {
                        _submitSuccess.value = true
                    }
                    is NetworkResult.Error -> {
                        _error.value = ErrorMessage.Custom(result.message ?: "提交失败")
                    }
                    is NetworkResult.Loading -> {
                        // 保持加载状态
                    }
                }
            } catch (e: Exception) {
                _error.value = ErrorMessage.Custom(e.message ?: "提交失败")
            }
        }
    }

    private suspend fun ensureCurrentUser() {
        if (currentUser != null) return
        
        when (val result = getProfileUseCase()) {
            is NetworkResult.Success -> {
                currentUser = result.data
            }
            is NetworkResult.Error -> {
                // 获取用户信息失败，使用默认权限
                currentUser = null
            }
            is NetworkResult.Loading -> {
                // 保持加载状态
            }
        }
    }

    private fun applyAccessControl(tree: List<Region>): List<Region> {
        val role = RoleType.fromValue(currentUser?.roleType)
        if (role == null || role == RoleType.SUPER_ADMIN) {
            return tree
        }
        val userRegionId = currentUser?.regionId ?: return tree
        val target = findRegionRecursive(tree, userRegionId) ?: return tree
        return listOf(target)
    }

    private fun rebuildRegionIndex(tree: List<Region>) {
        regionIndex.clear()
        fun walk(region: Region) {
            regionIndex[region.regionId] = region
            region.children.forEach(::walk)
        }
        tree.forEach(::walk)
    }

    private fun appendRegions(
        regions: List<Region>,
        depth: Int,
        parentLevel: RegionLevel?,
        result: MutableList<SelectableRegionItem>
    ) {
        for (region in regions) {
            if (!canManageRegion(region)) continue
            val level = resolveRegionLevel(region)
            val label = buildString {
                repeat(depth) { append("   ") }
                append(region.regionName)
            }
            result += SelectableRegionItem(region.regionId, label, level, parentLevel)
            if (region.children.isNotEmpty()) {
                appendRegions(region.children, depth + 1, level, result)
            }
        }
    }

    private fun canManageRegion(region: Region): Boolean {
        val role = RoleType.fromValue(currentUser?.roleType)
        if (role == null || role == RoleType.SUPER_ADMIN) return true
        val userRegionId = currentUser?.regionId ?: return false
        val levelPath = region.levelPath ?: return false
        return levelPath.split('/').contains(userRegionId.toString())
    }

    private fun findRegionRecursive(regions: List<Region>, targetId: Long): Region? {
        for (region in regions) {
            if (region.regionId == targetId) return region
            val match = findRegionRecursive(region.children, targetId)
            if (match != null) return match
        }
        return null
    }

    private fun applyRoleOptionsForSelection(item: SelectableRegionItem?) {
        val options = availableRolesFor(item)
        _roleOptions.value = options
        val current = _roleType.value
        _roleType.value = when {
            current != null && options.contains(current) -> current
            else -> options.firstOrNull()
        }
    }

    private fun availableRolesFor(item: SelectableRegionItem?): List<RoleType> {
        val level = item?.level ?: return emptyList()
        return when (level) {
            RegionLevel.HEADQUARTERS -> listOf(RoleType.SUPER_ADMIN)
            RegionLevel.PROVINCE -> listOf(RoleType.PROVINCE_ADMIN)
            RegionLevel.CITY -> listOf(RoleType.CITY_ADMIN)
            RegionLevel.COUNTY -> listOf(RoleType.COUNTY_ADMIN)
            RegionLevel.STATION -> {
                val parentLevel = item.parentLevel
                if (parentLevel == RegionLevel.CITY) {
                    listOf(RoleType.OPERATIONS_CENTER_ADMIN, RoleType.OPERATOR)
                } else {
                    listOf(RoleType.STATION_ADMIN, RoleType.OPERATOR)
                }
            }
        }
    }

    private fun determineInitialRegionId(items: List<SelectableRegionItem>): Long? {
        val current = regionId.value
        return when {
            current != null && items.any { it.id == current } -> current
            regionIdArg != null && items.any { it.id == regionIdArg } -> regionIdArg
            currentUser?.regionId != null && items.any { it.id == currentUser?.regionId } -> currentUser?.regionId
            else -> items.firstOrNull()?.id
        }
    }

    private fun resolveRegionLevel(region: Region?): RegionLevel? =
        RegionLevel.fromValue(region?.regionType ?: region?.level)

    data class SelectableRegionItem(
        val id: Long,
        val displayName: String,
        val level: RegionLevel?,
        val parentLevel: RegionLevel?
    )

    sealed interface ErrorMessage {
        data object MissingBasicInfo : ErrorMessage
        data object MissingRegion : ErrorMessage
        data object MissingRole : ErrorMessage
        data class Custom(val message: String) : ErrorMessage
    }
}










